// NetServer.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <stdio.h>
#include <winsock2.h>
#include <ws2tcpip.h>

// must be same as client
#define ITER 50000
#define ITER2 100
#define BUFLEN 131072

#define PORT 28100
#define STR_PORT "28100"


char servIPAddr[20] = "127.0.0.1";
char buf[BUFLEN];

#pragma comment (lib, "Ws2_32.lib")

void parse_args(int argc, char* argv[])
{
	int i = 1;
	while( i < argc ) {
		if(strcmp( argv[i], "-c") == 0 )
		{
			++i;
			if( i >= argc)
				break;
			strcpy_s(servIPAddr, argv[i]);
		}
		i++;
	}
}

int main(int argc, char* argv[])
{
	WSADATA wsaData;
	int iResult;
	SOCKET listenSocket = INVALID_SOCKET;
    SOCKET clientSocket = INVALID_SOCKET;
	int rttBytes = 0;
	int rttTotal = ITER;
	int recvTotal = ITER2 * BUFLEN;
	int recvBytes = 0;

	parse_args(argc, argv);
	
	iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (iResult != 0) {
        printf("WSAStartup failed with error: %d\n", iResult);
        return 1;
    }
    addrinfo *result = NULL;
    addrinfo hints;

	sockaddr_in servAddr;
	ZeroMemory(&servAddr, sizeof(servAddr));
	servAddr.sin_family = AF_INET;
    servAddr.sin_addr.s_addr = inet_addr(servIPAddr);
    servAddr.sin_port = htons(PORT);
	

	ZeroMemory(&hints, sizeof(hints));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;
    hints.ai_flags = AI_PASSIVE;
	
	iResult = getaddrinfo(NULL, STR_PORT, &hints, &result);
    if ( iResult != 0 ) {
        printf("getaddrinfo failed with error: %d\n", iResult);
        WSACleanup();
        return 1;
    }
	
	listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (listenSocket == INVALID_SOCKET) {
        printf("socket failed with error: %ld\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }
	// bind to local address
	iResult = bind( listenSocket, (SOCKADDR*) &servAddr, sizeof(servAddr) );
    if (iResult == SOCKET_ERROR) {
        printf("bind failed with error: %d\n", WSAGetLastError());
        closesocket(listenSocket);
        WSACleanup();
        return 1;
    }
	// listen 
	 iResult = listen(listenSocket, SOMAXCONN);
	 if (iResult == SOCKET_ERROR) {
        printf("listen failed with error: %d\n", WSAGetLastError());
        closesocket(listenSocket);
        WSACleanup();
        return 1;
	 } 
	 //else {
     //printf("Server listening for connection...\n");
	 //}
	 while(true) {
		 // wait for connection
		clientSocket = accept(listenSocket, NULL, NULL);
		if (clientSocket == INVALID_SOCKET) {
			printf("accept failed with error: %d\n", WSAGetLastError());
			closesocket(listenSocket);
			WSACleanup();
			return 1;
		}
		// close listen socket
		//closesocket(listenSocket);		

		// do round-trip test
		while(rttBytes < rttTotal) {
			rttBytes += recv(clientSocket, buf, BUFLEN, 0);
			//printf("received packet of length %i bytes\n", dataLen);
			send(clientSocket, buf, 1, 0);
		}

		// bandwidth test
		// upstream
		while(recvBytes < recvTotal) {
			recvBytes += recv(clientSocket, buf, BUFLEN, 0);
			//printf("received packet of length %i bytes\n", dataLen);
		
		}
		// downstream
		for(int i=0; i < ITER2; ++i)
		{
			send( clientSocket, buf, BUFLEN, 0 );
		}

		//shutdown client socket
		rttBytes = 0;
		recvBytes = 0;
		iResult = shutdown(clientSocket, SD_BOTH);
		if (iResult == SOCKET_ERROR) {
			printf("shutdown failed with error: %d\n", WSAGetLastError());
			closesocket(clientSocket);
			WSACleanup();
			return 1;
		}
		closesocket(clientSocket);

	 }

	 

	
    WSACleanup();

	return 0;
}

